using System;
using System.Data;
using PCSComMaterials.Inventory.BO;
using PCSComMaterials.Inventory.DS;
using PCSComProduct.Costing.DS;
using PCSComUtils.Common.BO;
using PCSComUtils.MasterSetup.DS;
using PCSComUtils.PCSExc;
using PCSComUtils.Common;
using PCSComSale.Order.DS;

namespace PCSComSale.Order.BO
{
	public class SOConfirmShipmentBO //: ISOConfirmShipmentBO
	{
		private const string THIS = "PCSComSale.Order.BO.SOConfirmShipmentBO";
		private const string CHECKSHIP = "CheckShip";
		private const string TRUE = "True";
		private const string SHIPPEDSTATUS = "Shipped";
		
		public SOConfirmShipmentBO()
		{
			//
			// TODO: Add constructor logic here
			//
		}


	
		public void Add(object pObjectDetail)
		{
			// TODO:  Add SOConfirmShipmentBO.Add implementation

		}
	
		public void Delete(object pObjectVO)
		{
			// TODO:  Add SOConfirmShipmentBO.Delete implementation

		}
	
		public object GetObjectVO(int pintID, string VOclass)
		{
			// TODO:  Add SOConfirmShipmentBO.GetObjectVO implementation
			return null;
		}
	
		public void Update(object pObjectDetail)
		{
			// TODO:  Add SOConfirmShipmentBO.Update implementation

		}
	
		public void UpdateDataSet(DataSet dstData)
		{
			// TODO:  Add SOConfirmShipmentBO.UpdateDataSet implementation

		}


		//**************************************************************************              
		///    <Description>
		///       This method uses to update all after ship items
		///    </Description>
		///    <Inputs>
		///       pdsDataShip
		///    </Inputs>
		///    <Outputs>
		///    </Outputs>
		///    <Returns>
		///    </Returns>
		///    <Authors>
		///       TuanDm
		///    </Authors>
		///    <History>
		///       Tuesday, February 22, 2005
		///    </History>
		///    <Notes>
		///    </Notes>
		//**************************************************************************
		//[AutoComplete(true)]
		public void ConfirmShipment(DataTable pdtbData, int pintCCNID, int pintMasLocID, DateTime pdtmShipDate)
		{
//			try
//			{
				SO_PackListMasterDS dsPackList = new SO_PackListMasterDS();
				SO_CommitInventoryDetailDS dsCommitInventory = new SO_CommitInventoryDetailDS();
				UtilsBO boUtils = new UtilsBO();
				InventoryUtilsBO boInventoryUtils = new InventoryUtilsBO();
				IV_MasLocCacheDS dsMasLocCache = new IV_MasLocCacheDS();
				ITM_CostDS dsCost = new ITM_CostDS();
				IV_LotFIFODS dsLotFiFo = new IV_LotFIFODS();
				foreach (DataRow drow in pdtbData.Rows)
				{
					if ((drow[CHECKSHIP].ToString().Trim() == TRUE)&&(drow[SO_PackListMasterTable.PACKLISTNO_FLD].ToString() != string.Empty))
					{
						//if row is in the packlist
						SO_PackListMasterVO voPackList = new SO_PackListMasterVO();
						voPackList = (SO_PackListMasterVO) dsPackList.GetObjectVO(drow[SO_PackListMasterTable.PACKLISTNO_FLD].ToString());
						voPackList.ShipDate = pdtmShipDate.Date;
						voPackList.Shipped = true;
						voPackList.Status = SHIPPEDSTATUS;
						dsPackList.Update(voPackList);

						//update commit inventory detail base on PackListMaster
						DataSet dstCommit = dsCommitInventory.ListCommitIventoryByPackListMasterNotShip(voPackList.PackListMasterID);
						foreach (DataRow drowCommit in dstCommit.Tables[0].Rows)
						{
							drowCommit[SO_CommitInventoryDetailTable.SHIPPED_FLD] = true;
							drowCommit[SO_CommitInventoryDetailTable.SHIPDATE_FLD] = pdtmShipDate;
							switch (int.Parse(drowCommit[ITM_ProductTable.COSTMETHOD_FLD].ToString()))
							{
								case (int) CostMethodEnum.AVG:
									drowCommit[SO_CommitInventoryDetailTable.STDCOST_FLD] = dsCost.GetItemCostTotalAmount21ByProductIDCCNID(int.Parse(drowCommit[SO_CommitInventoryDetailTable.PRODUCTID_FLD].ToString()), pintCCNID);
									drowCommit[SO_CommitInventoryDetailTable.COSTOFGOODSSOLD_FLD] = dsMasLocCache.GetAVGCostByProductIDMasLocID(int.Parse(drowCommit[SO_CommitInventoryDetailTable.PRODUCTID_FLD].ToString()), pintMasLocID);
									break;
								case (int) CostMethodEnum.ACT:
									drowCommit[SO_CommitInventoryDetailTable.STDCOST_FLD] = dsCost.GetItemCostTotalAmount21ByProductIDCCNID(int.Parse(drowCommit[SO_CommitInventoryDetailTable.PRODUCTID_FLD].ToString()), pintCCNID);
									drowCommit[SO_CommitInventoryDetailTable.COSTOFGOODSSOLD_FLD] = dsLotFiFo.GetActualCost21ProductIDCCNID(int.Parse(drowCommit[SO_CommitInventoryDetailTable.PRODUCTID_FLD].ToString()), pintCCNID);
									break;
								case (int) CostMethodEnum.STD:
									drowCommit[SO_CommitInventoryDetailTable.STDCOST_FLD] = dsCost.GetItemCostTotalAmount21ByProductIDCCNID(int.Parse(drowCommit[SO_CommitInventoryDetailTable.PRODUCTID_FLD].ToString()), pintCCNID);
									drowCommit[SO_CommitInventoryDetailTable.COSTOFGOODSSOLD_FLD] = dsCost.GetItemCostTotalAmount21ByProductIDCCNID(int.Parse(drowCommit[SO_CommitInventoryDetailTable.PRODUCTID_FLD].ToString()), pintCCNID);
									break;
							}
							UpdateToCache(drowCommit, pintCCNID, pintMasLocID);
							//SaveTransactionHistory
							MST_TransactionHistoryVO voMST_TransactionHistory = new MST_TransactionHistoryVO();
							voMST_TransactionHistory.CCNID = pintCCNID;
							voMST_TransactionHistory.PostDate = boUtils.GetDBDate();
							voMST_TransactionHistory.MasterLocationID = Convert.ToInt32(drowCommit[SO_CommitInventoryDetailTable.MASTERLOCATIONID_FLD]); 
							voMST_TransactionHistory.LocationID = Convert.ToInt32(drowCommit[SO_CommitInventoryDetailTable.LOCATIONID_FLD]); 
							if (drowCommit[SO_CommitInventoryDetailTable.BINID_FLD] != DBNull.Value) 
							{
								voMST_TransactionHistory.BinID = Convert.ToInt32(drowCommit[SO_CommitInventoryDetailTable.BINID_FLD]);
							}
							voMST_TransactionHistory.RefMasterID = Convert.ToInt32(drowCommit[SO_CommitInventoryDetailTable.COMMITINVENTORYMASTERID_FLD]);
							voMST_TransactionHistory.Lot = drowCommit[SO_CommitInventoryDetailTable.LOT_FLD].ToString();
							voMST_TransactionHistory.Serial = drowCommit[SO_CommitInventoryDetailTable.SERIAL_FLD].ToString(); 
							voMST_TransactionHistory.ProductID = Convert.ToInt32(drowCommit[SO_CommitInventoryDetailTable.PRODUCTID_FLD]);
							voMST_TransactionHistory.StockUMID = Convert.ToInt32(drowCommit[SO_CommitInventoryDetailTable.STOCKUMID_FLD]);
							voMST_TransactionHistory.Quantity = Convert.ToDecimal(drowCommit[SO_CommitInventoryDetailTable.COMMITQUANTITY_FLD]);
							
							voMST_TransactionHistory.TransDate = (DateTime)drowCommit[SO_CommitInventoryDetailTable.SHIPDATE_FLD];
							
							boInventoryUtils.SaveTransactionHistory(TransactionType.CONFIRM_SHIPMENT, (int)PurposeEnum.Ship, voMST_TransactionHistory);

						}
						dsCommitInventory.UpdateDataSetForPackListConfirm(dstCommit);
					}

					//update commit inventory detail base on SaleOrderMaster
					if ((drow[CHECKSHIP].ToString().Trim() == TRUE) && (drow[SO_PackListMasterTable.PACKLISTNO_FLD].ToString() == string.Empty))
					{
						DataSet dstCommit = dsCommitInventory.ListCommitIventoryBySaleOrderNotShip(drow[SO_SaleOrderMasterTable.CODE_FLD].ToString().Trim());
						foreach (DataRow drowCommit in dstCommit.Tables[0].Rows)
						{
							drowCommit[SO_CommitInventoryDetailTable.SHIPPED_FLD] = true;
							drowCommit[SO_CommitInventoryDetailTable.SHIPDATE_FLD] = pdtmShipDate;
                            switch (int.Parse(drowCommit[ITM_ProductTable.COSTMETHOD_FLD].ToString()))
							{
								case (int) CostMethodEnum.AVG:
									drowCommit[SO_CommitInventoryDetailTable.STDCOST_FLD] = dsCost.GetItemCostTotalAmount21ByProductIDCCNID(int.Parse(drowCommit[SO_CommitInventoryDetailTable.PRODUCTID_FLD].ToString()), pintCCNID);
									drowCommit[SO_CommitInventoryDetailTable.COSTOFGOODSSOLD_FLD] = dsMasLocCache.GetAVGCostByProductIDMasLocID(int.Parse(drowCommit[SO_CommitInventoryDetailTable.PRODUCTID_FLD].ToString()), pintMasLocID);
									break;
								case (int) CostMethodEnum.ACT:
									drowCommit[SO_CommitInventoryDetailTable.STDCOST_FLD] = dsCost.GetItemCostTotalAmount21ByProductIDCCNID(int.Parse(drowCommit[SO_CommitInventoryDetailTable.PRODUCTID_FLD].ToString()), pintCCNID);
									drowCommit[SO_CommitInventoryDetailTable.COSTOFGOODSSOLD_FLD] = dsLotFiFo.GetActualCost21ProductIDCCNID(int.Parse(drowCommit[SO_CommitInventoryDetailTable.PRODUCTID_FLD].ToString()), pintCCNID);
									break;
								case (int) CostMethodEnum.STD:
									drowCommit[SO_CommitInventoryDetailTable.STDCOST_FLD] = dsCost.GetItemCostTotalAmount21ByProductIDCCNID(int.Parse(drowCommit[SO_CommitInventoryDetailTable.PRODUCTID_FLD].ToString()), pintCCNID);
									drowCommit[SO_CommitInventoryDetailTable.COSTOFGOODSSOLD_FLD] = dsCost.GetItemCostTotalAmount21ByProductIDCCNID(int.Parse(drowCommit[SO_CommitInventoryDetailTable.PRODUCTID_FLD].ToString()), pintCCNID);
									break;
							}
							UpdateToCache(drowCommit, pintCCNID, pintMasLocID);
							//SaveTransactionHistory
							MST_TransactionHistoryVO voMST_TransactionHistory = new MST_TransactionHistoryVO();
							voMST_TransactionHistory.CCNID = pintCCNID;
							voMST_TransactionHistory.PostDate = boUtils.GetDBDate();
							voMST_TransactionHistory.MasterLocationID = Convert.ToInt32(drowCommit[SO_CommitInventoryDetailTable.MASTERLOCATIONID_FLD]); 
							voMST_TransactionHistory.LocationID = Convert.ToInt32(drowCommit[SO_CommitInventoryDetailTable.LOCATIONID_FLD]); 
							if (drowCommit[SO_CommitInventoryDetailTable.BINID_FLD] != DBNull.Value) 
							{
								voMST_TransactionHistory.BinID = Convert.ToInt32(drowCommit[SO_CommitInventoryDetailTable.BINID_FLD]);
							}
							voMST_TransactionHistory.RefMasterID = Convert.ToInt32(drowCommit[SO_CommitInventoryDetailTable.COMMITINVENTORYMASTERID_FLD]);
							voMST_TransactionHistory.Lot = drowCommit[SO_CommitInventoryDetailTable.LOT_FLD].ToString();
							voMST_TransactionHistory.Serial = drowCommit[SO_CommitInventoryDetailTable.SERIAL_FLD].ToString(); 
							voMST_TransactionHistory.ProductID = Convert.ToInt32(drowCommit[SO_CommitInventoryDetailTable.PRODUCTID_FLD]);
							voMST_TransactionHistory.StockUMID = Convert.ToInt32(drowCommit[SO_CommitInventoryDetailTable.STOCKUMID_FLD]);
							voMST_TransactionHistory.Quantity = Convert.ToDecimal(drowCommit[SO_CommitInventoryDetailTable.COMMITQUANTITY_FLD]);
							
							voMST_TransactionHistory.TransDate = (DateTime)drowCommit[SO_CommitInventoryDetailTable.SHIPDATE_FLD];
							
							boInventoryUtils.SaveTransactionHistory(TransactionType.CONFIRM_SHIPMENT, (int)PurposeEnum.Ship, voMST_TransactionHistory);

						}
						dsCommitInventory.UpdateDataSetForPackListConfirm(dstCommit);
					}
				}

				DataTable dtbSODetail;
				int intCountShip;
				SO_SaleOrderDetailDS dsSODetail = new SO_SaleOrderDetailDS();	
				SO_SaleOrderMasterDS dsSOMaster = new SO_SaleOrderMasterDS();	
				foreach (DataRow drow in pdtbData.Rows)
				{
					if (drow[CHECKSHIP].ToString().Trim() == TRUE)
					{
						intCountShip = 0;
						dtbSODetail = dsSODetail.List(drow[SO_SaleOrderMasterTable.CODE_FLD].ToString().Trim()).Tables[0];
						foreach (DataRow drowDetail in dtbSODetail.Rows)
						{
							if (dsSODetail.IsRemainQuantityNotShip(int.Parse(drowDetail[SO_SaleOrderDetailTable.SALEORDERDETAILID_FLD].ToString().Trim())))
							{
								intCountShip++;
							}
						}
						if (intCountShip == dtbSODetail.Rows.Count)
						{
							dsSOMaster.UpdateShipComplete(drow[SO_SaleOrderMasterTable.CODE_FLD].ToString().Trim());
						}
					}
				}
//			}
//			catch (PCSDBException ex)
//			{
//				throw ex;
//			}
//			catch (Exception ex)
//			{
//				throw ex;
//			}
		}


		/// <summary>
		/// List confirmable from commit inventory
		/// </summary>
		/// <param name="pintCommitMasterID"></param>
		/// <returns></returns>
		//[AutoComplete(true)]
		public DataSet ListConfirmable(int pintCommitMasterID)
		{
			SO_CommitInventoryDetailDS dsDetail = new SO_CommitInventoryDetailDS();
			return dsDetail.ListToConfirm(pintCommitMasterID);
		}
		//[AutoComplete(true)]
		public DataSet List(int pintConfirmMasterID)
		{
			SO_ConfirmShipDetailDS dsDetail = new SO_ConfirmShipDetailDS();
			return dsDetail.ListByMaster(pintConfirmMasterID);
		}


		//**************************************************************************              
		///    <Description>
		///    Update data in Cache after confirm shipment
		///    </Description>
		///    <Inputs>
		///    </Inputs>
		///    <Outputs>
		///    </Outputs>
		///    <Returns>
		///       void
		///    </Returns>
		///    <Authors>
		///       TuanDm
		///    </Authors>
		///    <History>
		///       Friday, Apr 29, 2005
		///    </History>
		///    <Notes>
		///    </Notes>
		//**************************************************************************
		private void UpdateToCache(DataRow pdrowData, int pintCCNID, int pintMasLocID)
		{
			try
			{
				Decimal dcmQuantity = Decimal.Parse(pdrowData[SO_CommitInventoryDetailTable.COMMITQUANTITY_FLD].ToString());
				int intProductID =	int.Parse(pdrowData[SO_CommitInventoryDetailTable.PRODUCTID_FLD].ToString());
				int intLocationID =0;
				int intBinID = 0;
				new IV_MasLocCacheDS().UpdateSubtractCommitQuantity(pintCCNID, pintMasLocID, intProductID, dcmQuantity);
				if (pdrowData[SO_CommitInventoryDetailTable.LOCATIONID_FLD].ToString() != string.Empty)
				{
					intLocationID = int.Parse(pdrowData[SO_CommitInventoryDetailTable.LOCATIONID_FLD].ToString());
					new IV_LocationCacheDS().UpdateSubtractCommitQuantity(pintCCNID, pintMasLocID, intLocationID, intProductID, dcmQuantity);
					if (pdrowData[SO_CommitInventoryDetailTable.BINID_FLD].ToString() != string.Empty)
					{
						intBinID = int.Parse(pdrowData[SO_CommitInventoryDetailTable.BINID_FLD].ToString());
						new IV_BinCacheDS().UpdateSubtractCommitQuantity(pintCCNID, pintMasLocID, intLocationID, intBinID, intProductID, dcmQuantity);
					}
					else
					{
						intBinID = 0;
					}
					new InventoryUtilsBO().UpdateSubtractOHQuantity(pintCCNID, pintMasLocID, intLocationID, intBinID, intProductID, dcmQuantity, string.Empty, string.Empty);
				}
			}
			catch (PCSDBException ex)
			{
				throw ex;
			}
			catch (Exception ex)
			{
				throw new Exception(ex.Message, ex);
			}

		}
	}
}
